﻿/*
 * This example shows how to write a client that subscribes to a topic and does
 * not do anything other than handle the messages that are received.
 */

#include <mosquitto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include <pthread.h>

#if defined(WITH_TLS)
#include <openssl/ssl.h>
#endif

const char* topic = "example/temperature";

/* Callback called when the client receives a CONNACK message from the broker. */
void on_connect(struct mosquitto* mosq, void* obj, int reason_code)
{
    int rc;
    /* Print out the connection result. mosquitto_connack_string() produces an
	 * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0
	 * clients is mosquitto_reason_string().
	 */
    printf("on_connect: %s\n", mosquitto_connack_string(reason_code));
    if (reason_code != 0)
    {
        /* If the connection fails for any reason, we don't want to keep on
		 * retrying in this example, so disconnect. Without this, the client
		 * will attempt to reconnect. */
        mosquitto_disconnect(mosq);
    }

    /* Making subscriptions in the on_connect() callback means that if the
	 * connection drops and is automatically resumed by the client, then the
	 * subscriptions will be recreated when the client reconnects. */
    printf("subscribe: [\n    %s\n]\n", topic);
    rc = mosquitto_subscribe(mosq, NULL, topic, 0);
    if (rc != MOSQ_ERR_SUCCESS)
    {
        fprintf(stderr, "Error subscribing: %s\n", mosquitto_strerror(rc));
        /* We might as well disconnect if we were unable to subscribe */
        mosquitto_disconnect(mosq);
    }
}

void on_disconnect(struct mosquitto* mosq, void* obj, int reason_code)
{
    fprintf(stderr, "Error disconnect: %d(%s)\n", reason_code, mosquitto_reason_string(reason_code));
}

///* Callback called when the broker sends a SUBACK in response to a SUBSCRIBE. */
//void on_subscribe(struct mosquitto* mosq, void* obj, int mid, int qos_count, const int* granted_qos)
//{
//    int  i;
//    bool have_subscription = false;
//
//    /* In this example we only subscribe to a single topic at once, but a
//	 * SUBSCRIBE can contain many topics at once, so this is one way to check
//	 * them all. */
//    for (i = 0; i < qos_count; i++)
//    {
//        printf("on_subscribe: %d:granted qos = %d\n", i, granted_qos[i]);
//        if (granted_qos[i] <= 2)
//        {
//            have_subscription = true;
//        }
//    }
//    if (have_subscription == false)
//    {
//        /* The broker rejected all of our subscriptions, we know we only sent
//		 * the one SUBSCRIBE, so there is no point remaining connected. */
//        fprintf(stderr, "Error: All subscriptions rejected.\n");
//        mosquitto_disconnect(mosq);
//    }
//}

/* Callback called when the client receives a message. */
void on_message(struct mosquitto* mosq, void* obj, const struct mosquitto_message* msg)
{
    /* This blindly prints the payload, but the payload can be anything so take care. */
    printf("%s %d %s\n", msg->topic, msg->qos, (char*)msg->payload);
}

int main(int argc, char* argv[])
{
	int ssl = 0;
    if (argc > 1)
        ssl = atoi(argv[1]);

    struct mosquitto* mosq;
    int               rc;

    /* Required before calling other mosquitto functions */
    mosquitto_lib_init();

    /* Create a new client instance.
	 * id = NULL -> ask the broker to generate a client id for us
	 * clean session = true -> the broker should remove old sessions when we connect
	 * obj = NULL -> we aren't passing any of our private data for callbacks
	 */
    mosq = mosquitto_new(NULL, true, NULL);
    if (mosq == NULL)
    {
        fprintf(stderr, "Error: Out of memory.\n");
        return 1;
    }

    /* Configure callbacks. This should be done before connecting ideally. */
    mosquitto_connect_callback_set(mosq, on_connect);
    //mosquitto_subscribe_callback_set(mosq, on_subscribe);
    mosquitto_message_callback_set(mosq, on_message);
    mosquitto_disconnect_callback_set(mosq, [](struct mosquitto* mosq, void* obj, int reason_code)
        {
            fprintf(stderr, "---- disconnect: %d(%s)\n", reason_code, mosquitto_reason_string(reason_code));
        }
    );

    fprintf(stderr, "tls %d\r\n", ssl);
if (ssl) 
{
    if (mosquitto_tls_set(mosq, "./ssl/cacert.pem",
        "./ssl",
        "./ssl/client-cert.pem",
        "./ssl/client-key.pem", NULL) != MOSQ_ERR_SUCCESS) {
        fprintf(stderr, "Error: mosquitto_tls_set\r\n");
        return -1;
    }
    mosquitto_tls_opts_set(mosq, 0, "tlsv1.2", NULL);
}

    /* Connect to test.mosquitto.org on port 1883, with a keepalive of 60 seconds.
	 * This call makes the socket connection only, it does not complete the MQTT
	 * CONNECT/CONNACK flow, you should use mosquitto_loop_start() or
	 * mosquitto_loop_forever() for processing net traffic. */
if (ssl)
    rc = mosquitto_connect(mosq, "42.192.86.26", 8883, 60);
else
    rc = mosquitto_connect(mosq, "42.192.86.26", 21883, 60);
    if (rc != MOSQ_ERR_SUCCESS)
    {
        mosquitto_destroy(mosq);
        fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc));
        return 1;
    }

    /* Run the network loop in a blocking call. The only thing we do in this
	 * example is to print incoming messages, so a blocking call here is fine.
	 *
	 * This call will continue forever, carrying automatic reconnections if
	 * necessary, until the user calls mosquitto_disconnect().
	 */
    mosquitto_loop_forever(mosq, -1, 1);

    mosquitto_lib_cleanup();
    return 0;
}
